package com.gxar.timeline.server.db.service;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxar.common.entity.PageResult;
import com.gxar.common.entity.Result;
import com.gxar.common.exception.APIRuntimeException;
import com.gxar.common.utils.PageUtils;
import com.gxar.common.utils.SnowFlakeUtils;
import com.gxar.timeline.server.base.common.enums.CurrencyEnum;
import com.gxar.timeline.server.base.common.enums.HmdPageEnum;
import com.gxar.timeline.server.base.common.enums.ProductCategoryEnum;
import com.gxar.timeline.server.base.common.utils.PriceUnitParser;
import com.gxar.timeline.server.base.handler.hmd.listener.HmdImportListener;
import com.gxar.timeline.server.base.model.ResultCodeEnum;
import com.gxar.timeline.server.base.model.hmd.mapper.HmdProductMapStruct;
import com.gxar.timeline.server.base.model.hmd.mapper.HmdProductModelMapStruct;
import com.gxar.timeline.server.base.model.hmd.mapper.ProductPictureMapStruct;
import com.gxar.timeline.server.base.model.hmd.vo.BaseModelVO;
import com.gxar.timeline.server.base.model.hmd.vo.HmdImportVO;
import com.gxar.timeline.server.base.model.hmd.vo.PictureVO;
import com.gxar.timeline.server.base.model.hmd.vo.request.HmdPageRequest;
import com.gxar.timeline.server.base.model.hmd.vo.request.HmdProductCreateRequest;
import com.gxar.timeline.server.base.model.hmd.vo.request.HmdProductUpdateRequest;
import com.gxar.timeline.server.base.model.hmd.vo.response.*;
import com.gxar.timeline.server.db.mapper.HmdCompanyMapper;
import com.gxar.timeline.server.db.mapper.HmdProductMapper;
import com.gxar.timeline.server.db.mapper.HmdProductModelMapper;
import com.gxar.timeline.server.db.mapper.ProductPictureMapper;
import com.gxar.timeline.server.db.model.HmdCompanyEntity;
import com.gxar.timeline.server.db.model.HmdProductEntity;
import com.gxar.timeline.server.db.model.HmdProductModelEntity;
import com.gxar.timeline.server.db.model.ProductPictureEntity;
import com.gxar.timeline.server.db.repository.HmdCompanyRepository;
import com.gxar.timeline.server.db.repository.HmdProductModelRepository;
import com.gxar.timeline.server.db.repository.HmdProductRepository;
import com.gxar.timeline.server.db.repository.ProductPictureRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author linsy
 * @version 1.0
 * @created 2023/9/22 09:34
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class HmdService {

    private final HmdProductMapper hmdProductMapper;
    private final HmdProductModelMapper hmdProductModelMapper;
    private final ProductPictureMapper productPictureMapper;

    private final HmdCompanyRepository hmdCompanyRepository;
    private final HmdProductRepository hmdProductRepository;
    private final HmdProductModelRepository hmdProductModelRepository;
    private final ProductPictureRepository productPictureRepository;

    private final HmdCompanyMapper companyMapper;

    /**
     * 头显排行列表
     *
     * @param request 请求
     * @return 响应
     */
    public Result<PageResult<HmdPageResponse>> pageList(HmdPageRequest request) {
        Map<String, String> search = request.getSearch();
        String companyName = null;
        String productName = null;
        if (search != null && !search.isEmpty()) {
            companyName = search.get(HmdPageEnum.COMPANY_NAME.getName());
            productName = search.get(HmdPageEnum.PRODUCT_NAME.getName());
        }
        Page<Object> page = PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<HmdPageResponse> hmdPageResponses = hmdProductMapper.pageList(null, companyName, productName);
        if (CollectionUtils.isNotEmpty(hmdPageResponses)) {
            List<String> productIdList = hmdPageResponses.stream().map(HmdPageResponse::getProductId).collect(Collectors.toList());
            List<HmdProductModelEntity> hmdProductModelEntityList = hmdProductModelMapper.findInProductId(productIdList);
            List<ProductPictureEntity> productPictureEntityList = productPictureMapper.findInProductIdAndCategory(ProductCategoryEnum.HEAD_DISPLAY.getCode(), productIdList);
            Map<Long, List<HmdProductModelEntity>> hmdProductModelMap = Optional.ofNullable(hmdProductModelEntityList).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(HmdProductModelEntity::getProductId));
            Map<Long, List<ProductPictureEntity>> productPictureMap = Optional.ofNullable(productPictureEntityList).orElse(Collections.emptyList()).stream().collect(Collectors.groupingBy(ProductPictureEntity::getProductId));
            for (HmdPageResponse hmdPageResponse : hmdPageResponses) {
                String productId = hmdPageResponse.getProductId();
                List<HmdProductModelEntity> productModelEntities = hmdProductModelMap.get(Long.valueOf(productId));
                hmdPageResponse.setModels(HmdProductModelMapStruct.INSTANCE.entitiesToVo(productModelEntities));
                List<ProductPictureEntity> productPictureEntities = productPictureMap.get(Long.valueOf(productId));
                hmdPageResponse.setPictures(ProductPictureMapStruct.INSTANCE.entitiesToVo(productPictureEntities));
            }
        }
        PageInfo<HmdPageResponse> hmdPageResponsePageInfo = new PageInfo<>(hmdPageResponses);
        hmdPageResponsePageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(hmdPageResponsePageInfo, hmdPageResponses);
    }

    @Transactional(rollbackFor = Throwable.class)
    public HmdImportResponse importHmd(MultipartFile file) throws IOException {
        HmdImportResponse response = new HmdImportResponse();
        HmdImportListener<HmdImportVO> hmdImportListener = new HmdImportListener<>();
        EasyExcel.read(file.getInputStream(), HmdImportVO.class, hmdImportListener)
                .sheet()
                .doRead();

        // 字段解析错误
        StringBuilder totalErrorMessage = hmdImportListener.getTotalErrorMessage();
        String failReason = totalErrorMessage.toString();
        if (StringUtils.isNotBlank(failReason)) {
            // 状态改成处理失败
            Integer failedCount = hmdImportListener.getFailedCount();
            totalErrorMessage.insert(0, "失败条数总计：" + failedCount + "条，以下为部分失败内容，未展示内容请按照下方的失败内容自行排查。\n");
            String totalErrorStr = totalErrorMessage.toString();
            String totalError = totalErrorStr.length() > 1000 ? totalErrorStr.substring(0, 1000) : totalErrorStr;
            response.setFailReason(totalError);
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, totalError);
        }

        //成功导入的广告账号
        List<HmdImportVO> successList = hmdImportListener.getSuccessList();
        if (CollectionUtils.isEmpty(successList)) {
            response.setFailReason("表格数据为空");
            throw new APIRuntimeException(ResultCodeEnum.EXCEL_ERROR, "表格数据为空");
        }

        List<HmdCompanyEntity> hmdCompanyEntityList = hmdCompanyRepository.findAll();
        List<HmdProductEntity> hmdProductEntityList = hmdProductRepository.findAll();
        Map<String, HmdCompanyEntity> hmdCompanyEntityMap = hmdCompanyEntityList.stream().collect(Collectors.toMap(HmdCompanyEntity::getName, t -> t, (t1, t2) -> t1));
        Map<String, Map<Long, HmdProductEntity>> productEntityMap = hmdProductEntityList.stream().collect(Collectors.groupingBy(HmdProductEntity::getName, Collectors.toMap(HmdProductEntity::getCompanyId, t -> t, (t1, t2) -> t1)));

        List<HmdProductModelEntity> hmdProductModelEntityList = new ArrayList<>();
        List<ProductPictureEntity> productPictureEntityList = new ArrayList<>();
        for (HmdImportVO hmdImportVo : successList) {
            PriceUnitParser.PriceUnit priceInfo = PriceUnitParser.parsePriceUnit(hmdImportVo.getPrice());
            Optional<CurrencyEnum> priceCurrency = CurrencyEnum.getByUnit(priceInfo.getUnit());
            if (!priceCurrency.isPresent()) {
                totalErrorMessage.append(hmdImportVo.getPrice()).append("价格单位不匹配").append("\n");
                continue;
            }
            // 产品型号
            HmdProductModelEntity hmdProductModelEntity = buildProductModel(hmdImportVo, priceInfo, priceCurrency.get());

            HmdCompanyEntity hmdCompanyEntity = hmdCompanyEntityMap.get(hmdImportVo.getCompanyName());
            // 公司存在
            if (Objects.nonNull(hmdCompanyEntity)) {
                Map<Long, HmdProductEntity> hmdProductEntityMap = productEntityMap.get(hmdImportVo.getProductName());
                if (hmdProductEntityMap != null && !hmdProductEntityMap.isEmpty()) {
                    HmdProductEntity hmdProductEntity = hmdProductEntityMap.get(hmdCompanyEntity.getId());
                    if (Objects.nonNull(hmdProductEntity)) {
                        hmdProductModelEntity.setProductId(hmdProductEntity.getId());
                    } else {
                        // 有这个产品但是不是这个品牌的
                        buildSaveProduct(hmdProductModelEntity, hmdCompanyEntity.getId(), hmdImportVo, hmdProductEntityList, productEntityMap, productPictureEntityList);
                    }
                } else {
                    // 没有这个产品
                    buildSaveProduct(hmdProductModelEntity, hmdCompanyEntity.getId(), hmdImportVo, hmdProductEntityList, productEntityMap, productPictureEntityList);
                }
            } else {
                // 公司不存在
                // 创建公司创建产品
                HmdCompanyEntity companyEntity = buildCompany(hmdImportVo);
                hmdCompanyEntityList.add(companyEntity);
                hmdCompanyEntityMap.put(companyEntity.getName(), companyEntity);
                buildSaveProduct(hmdProductModelEntity, companyEntity.getId(), hmdImportVo, hmdProductEntityList, productEntityMap, productPictureEntityList);
            }
            hmdProductModelEntityList.add(hmdProductModelEntity);
        }
        hmdProductModelRepository.saveAll(hmdProductModelEntityList);
        hmdProductRepository.saveAll(hmdProductEntityList);
        hmdCompanyRepository.saveAll(hmdCompanyEntityList);
        productPictureRepository.saveAll(productPictureEntityList);
        response.setFailReason(totalErrorMessage.toString());
        response.setSuccessNumber(hmdProductModelEntityList.size());
        return response;
    }

    /**
     * 构建头显型号
     *
     * @param hmdImportVo  头显导入
     * @param priceInfo    价格信息
     * @param currencyEnum 币种
     * @return 头显型号实体
     */
    private HmdProductModelEntity buildProductModel(HmdImportVO hmdImportVo, PriceUnitParser.PriceUnit priceInfo, CurrencyEnum currencyEnum) {
        HmdProductModelEntity hmdProductModelEntity = new HmdProductModelEntity();
        hmdProductModelEntity.setPrice(priceInfo.getPrice());
        hmdProductModelEntity.setPurchaseLink(hmdImportVo.getPurchaseLink());
        hmdProductModelEntity.setSymbol(currencyEnum.getSymbol());
        hmdProductModelEntity.setDescription(hmdImportVo.getDescription());
        hmdProductModelEntity.setCreatedAt(new Date());
        return hmdProductModelEntity;
    }

    /**
     * 构建头显公司品牌
     *
     * @param hmdImportVo 头显导入
     * @return 公司品牌实体
     */
    private HmdCompanyEntity buildCompany(HmdImportVO hmdImportVo) {
        HmdCompanyEntity hmdCompanyEntity = new HmdCompanyEntity();
        hmdCompanyEntity.setId(Long.parseLong(SnowFlakeUtils.getInstance().nextId()));
        hmdCompanyEntity.setName(hmdImportVo.getCompanyName());
        hmdCompanyEntity.setCreatedAt(new Date());
        return hmdCompanyEntity;
    }

    /**
     * 新创建的产品，保存到数据库的集合中
     *
     * @param hmdProductModelEntity    头显型号
     * @param companyId                所属品牌
     * @param hmdImportVo              头显导入数据
     * @param hmdProductEntityList     数据库保存产品实体
     * @param productEntityMap         内存临时产品数据
     * @param productPictureEntityList 产品照片实体
     */
    private void buildSaveProduct(HmdProductModelEntity hmdProductModelEntity, Long companyId, HmdImportVO hmdImportVo,
                                  List<HmdProductEntity> hmdProductEntityList, Map<String, Map<Long, HmdProductEntity>> productEntityMap,
                                  List<ProductPictureEntity> productPictureEntityList) {
        HmdProductEntity productEntity = buildHmdProductEntity(companyId, hmdImportVo);
        hmdProductModelEntity.setProductId(productEntity.getId());
        hmdProductEntityList.add(productEntity);
        HashMap<Long, HmdProductEntity> productMap = new HashMap<>();
        productMap.put(companyId, productEntity);
        productEntityMap.put(productEntity.getName(), productMap);
        // 产品照片
        if (StringUtils.isNotBlank(hmdImportVo.getPictureUrl())) {
            ProductPictureEntity productPictureEntity = buildProductPicture(productEntity.getId(), hmdImportVo);
            productPictureEntityList.add(productPictureEntity);
        }
    }

    /**
     * 构建产品图片
     *
     * @param productId   产品id
     * @param hmdImportVo 导入实体
     * @return 产品图片实体
     */
    private ProductPictureEntity buildProductPicture(Long productId, HmdImportVO hmdImportVo) {
        ProductPictureEntity productPictureEntity = new ProductPictureEntity();
        productPictureEntity.setProductId(productId);
        productPictureEntity.setUrl(hmdImportVo.getPictureUrl());
        productPictureEntity.setMain(true);
        productPictureEntity.setCreatedAt(new Date());
        productPictureEntity.setCategory(ProductCategoryEnum.HEAD_DISPLAY.getCode());
        return productPictureEntity;
    }

    /**
     * 构建产品实体
     *
     * @param companyId   公司品牌id
     * @param hmdImportVo 头显导入
     * @return 头显产品实体
     */
    private HmdProductEntity buildHmdProductEntity(Long companyId, HmdImportVO hmdImportVo) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd");
        HmdProductEntity hmdProductEntity = new HmdProductEntity();
        hmdProductEntity.setId(Long.parseLong(SnowFlakeUtils.getInstance().nextId()));
        hmdProductEntity.setName(hmdImportVo.getProductName());
        hmdProductEntity.setCompanyId(companyId);
        if (StringUtils.isNotBlank(hmdImportVo.getListedDate())) {
            try {
                hmdProductEntity.setListedDate(simpleDateFormat.parse(hmdImportVo.getListedDate()));
            } catch (ParseException e) {
                log.error("[{}] 日期格式错误", hmdImportVo.getProductName());
            }
        }
        if (StringUtils.isNotBlank(hmdImportVo.getIssuanceDate())) {
            try {
                hmdProductEntity.setIssuanceDate(simpleDateFormat.parse(hmdImportVo.getIssuanceDate()));
            } catch (ParseException e) {
                log.error("[{}] 日期格式错误", hmdImportVo.getProductName());
            }
        }
        hmdProductEntity.setCreatedAt(new Date());
        return hmdProductEntity;
    }

    /**
     * 创建产品
     *
     * @param request 请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public HmdProductCreateResponse createProduct(HmdProductCreateRequest request) {
        String name = request.getName();
        Long companyId = request.getCompanyId();
        companyId = checkCompany(companyId, request.getCompanyName());
        HmdProductEntity hmdProductEntity = hmdProductMapper.findOneByCompanyIdAndName(companyId, name);
        if (Objects.nonNull(hmdProductEntity)) {
            throw new APIRuntimeException(ResultCodeEnum.PRODUCT_EXIST);
        }
        HmdProductEntity entity = HmdProductMapStruct.INSTANCE.createToEntity(request);
        Long productId = Long.parseLong(SnowFlakeUtils.getInstance().nextId());
        entity.setId(productId);
        entity.setCreatedAt(new Date());
        entity.setCompanyId(companyId);
        HmdProductEntity productEntitySaved = hmdProductRepository.save(entity);
        List<BaseModelVO> models = request.getModels();
        List<HmdProductModelEntity> hmdProductModelEntityList = HmdProductModelMapStruct.INSTANCE.basesToEntities(models);
        boolean modelSymbolError = hmdProductModelEntityList.stream().anyMatch(e -> StringUtils.isBlank(e.getSymbol()));
        if (modelSymbolError) {
            throw new APIRuntimeException(ResultCodeEnum.PRICE_UNIT_ERROR);
        }
        hmdProductModelEntityList.forEach(e -> {
            e.setProductId(productId);
            e.setCreatedAt(new Date());
        });
        hmdProductModelRepository.saveAll(hmdProductModelEntityList);
        List<PictureVO> pictures = request.getPictures();
        List<ProductPictureEntity> productPictureEntities = ProductPictureMapStruct.INSTANCE.voListToEntities(pictures);
        boolean pictureError = productPictureEntities.stream().anyMatch(e -> StringUtils.isBlank(e.getUrl()));
        if (pictureError) {
            throw new APIRuntimeException(ResultCodeEnum.PRODUCT_PICTURE_ERROR);
        }
        productPictureEntities.forEach(e -> {
            e.setProductId(productId);
            e.setCategory(ProductCategoryEnum.HEAD_DISPLAY.getCode());
            e.setCreatedAt(new Date());
            // 第一张默认主图
            e.setMain(productPictureEntities.indexOf(e) == 0);
        });
        productPictureRepository.saveAll(productPictureEntities);
        return HmdProductMapStruct.INSTANCE.entityToCreate(productEntitySaved);
    }

    /**
     * 校验名称是否存在
     *
     * @param companyId   公司id
     * @param companyName 公司名称
     * @return 响应
     */
    private Long checkCompany(Long companyId, String companyName) {
        if (Objects.isNull(companyId) && StringUtils.isBlank(companyName)) {
            throw new APIRuntimeException(ResultCodeEnum.COMPANY_NOT_NULL);
        }
        if (Objects.isNull(companyId)) {
            HmdCompanyEntity companyEntity = companyMapper.findOneByName(companyName);
            if (Objects.isNull(companyEntity)) {
                throw new APIRuntimeException(ResultCodeEnum.COMPANY_NOT_EXIST_CREATE);
            }
            companyId = companyEntity.getId();
        }
        return companyId;
    }

    /**
     * 更新产品
     *
     * @param id      产品id
     * @param request 请求
     * @return 响应
     */
    @Transactional(rollbackFor = Throwable.class)
    public HmdProductUpdateResponse updateProduct(Long id, HmdProductUpdateRequest request) {
        String name = request.getName();
        Long companyId = request.getCompanyId();
        companyId = checkCompany(companyId, request.getCompanyName());
        Optional<HmdProductEntity> hmdProductEntityOptional = hmdProductRepository.findById(id);
        if (!hmdProductEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PRODUCT_NOT_EXIST);
        }
        HmdProductEntity oriProductEntity = hmdProductEntityOptional.get();
        if (!oriProductEntity.getName().equals(name) || !oriProductEntity.getCompanyId().equals(companyId)) {
            HmdProductEntity hmdProductEntity = hmdProductMapper.findOneByCompanyIdAndName(companyId, name);
            if (Objects.nonNull(hmdProductEntity)) {
                throw new APIRuntimeException(ResultCodeEnum.PRODUCT_EXIST);
            }
        }
        Long productId = oriProductEntity.getId();
        HmdProductEntity productEntity = HmdProductMapStruct.INSTANCE.updateToEntity(request);
        productEntity.setId(productId);
        productEntity.setCompanyId(companyId);
        productEntity.setCreatedAt(oriProductEntity.getCreatedAt());
        HmdProductEntity productUpdated = hmdProductRepository.save(productEntity);
        List<BaseModelVO> models = request.getModels();
        List<HmdProductModelEntity> hmdProductModelEntityList = HmdProductModelMapStruct.INSTANCE.basesToEntities(models);
        boolean modelSymbolError = hmdProductModelEntityList.stream().anyMatch(e -> StringUtils.isBlank(e.getSymbol()));
        if (modelSymbolError) {
            throw new APIRuntimeException(ResultCodeEnum.PRICE_UNIT_ERROR);
        }
        hmdProductModelEntityList.forEach(e -> {
            e.setProductId(productId);
            e.setCreatedAt(new Date());
        });
        hmdProductModelMapper.deleteByProductId(productId);
        hmdProductModelRepository.saveAll(hmdProductModelEntityList);

        List<PictureVO> pictures = request.getPictures();
        List<ProductPictureEntity> productPictureEntities = ProductPictureMapStruct.INSTANCE.voListToEntities(pictures);
        boolean pictureError = productPictureEntities.stream().anyMatch(e -> StringUtils.isBlank(e.getUrl()));
        if (pictureError) {
            throw new APIRuntimeException(ResultCodeEnum.PRODUCT_PICTURE_ERROR);
        }
        productPictureEntities.forEach(e -> {
            e.setProductId(productId);
            e.setCategory(ProductCategoryEnum.HEAD_DISPLAY.getCode());
            e.setCreatedAt(new Date());
            // 第一张默认主图
            e.setMain(productPictureEntities.indexOf(e) == 0);
        });
        productPictureMapper.deleteByProductId(productId);
        productPictureRepository.saveAll(productPictureEntities);
        return HmdProductMapStruct.INSTANCE.entityToUpdate(productUpdated);
    }

    /**
     * 产品详情
     *
     * @param id 产品id
     * @return 产品详情
     */
    public HmdProductDetailResponse productDetail(Long id) {
        List<HmdPageResponse> hmdPageResponses = hmdProductMapper.pageList(id, null, null);
        if (CollectionUtils.isNotEmpty(hmdPageResponses) && Objects.nonNull(hmdPageResponses.get(0))) {
            HmdPageResponse hmdPageResponse = hmdPageResponses.get(0);
            HmdProductDetailResponse detail = HmdProductMapStruct.INSTANCE.pageToDetail(hmdPageResponse);
            List<HmdProductModelEntity> hmdProductModelEntityList = hmdProductModelMapper.findByProductId(id);
            detail.setModels(HmdProductModelMapStruct.INSTANCE.entitiesToVo(hmdProductModelEntityList));
            List<ProductPictureEntity> productPictureEntities = productPictureMapper.findByProductId(id);
            detail.setPictures(ProductPictureMapStruct.INSTANCE.entitiesToVo(productPictureEntities));
            return detail;
        }
        return null;
    }

    /**
     * 删除产品
     *
     * @param id 产品id
     * @return 是否成功
     */
    public Boolean deleteProduct(Long id) {
        Optional<HmdProductEntity> hmdProductEntityOptional = hmdProductRepository.findById(id);
        if (!hmdProductEntityOptional.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.PRODUCT_NOT_EXIST);
        }
        hmdProductRepository.deleteById(id);
        hmdProductModelMapper.deleteByProductId(id);
        productPictureMapper.deleteByProductId(id);
        return true;
    }
}
